<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>原型&原型链&构造函数</title>
</head>
<body>
    <script>
        // 构造函数
        function Foo(){
            this.a = 1
        }
        // 构造函数可以用new执行
        // 如果用new执行，当前的this指向为实例对象

        //Foo.prototype => 原型对象
        Foo.prototype = { // 修改原型必须在实例之前修改
            aa: 10,
            bb: function(){
                console.log(20);
            },
            // 修改原型后，会出现没有constructor
            constructor: Foo // constructor指向构造函数
        } //foo实例对象的原型 === Foo构造函数的原型

        // foo 实例对象
        var foo = new Foo()

        // 实例对象可以拿到原型对象（Foo.prototype）的属性和方法（foo）
        // console.log(foo.aa);
        // foo.bb();
        console.log(foo);
        
        // 访问原型有两种方式
        // 1、通过实例对象 xx.__proto__
        // 2、通过构造函数 XX.prototype
        console.log(foo.__proto__ === Foo.prototype);
        
        // constructor是原型上一个属性
        console.log(Foo.prototype);

        console.log(foo.__proto__.__proto__ === Object.prototype);
        console.log(Foo.prototype.__proto__ === Object.prototype);
        // 所有对象的公共原型 Object.prototype

        // 不建议通过__proto__修改原型，可以通过prototype修改原型
        // es6获取原型
        console.log(Object.getPrototypeOf(foo))
        console.log(Object.getPrototypeOf(foo) === Foo.prototype)
        
        // 原型上的constructor === 构造函数Foo
        console.log(Foo.prototype.constructor === Foo);
        console.log(foo.__proto__.constructor === Foo);
        // 实例化对象可以访问它自己以及它原型上的api
        console.log(foo.constructor === Foo)
    </script>
</body>
</html>